;---------------------------------------------------------------------------
; FileName: enhance.asm
; Description:
; Enhance the fingerprint image,first Normalize the image,set the image mean
; variance to desired value.then divide the image into block image
; do image region masking
; written by wang zhigang
; Date:   06/25/2000
;---------------------------------------------------------------------------
        .mmregs
        .include "fisc54.inc"
        .ref IMAGEADDR
        .ref ThetaArray,LightArray,FreqArray,Theta
        .ref Sqroot,CalAngle,ReCalAngle,TangleValue,CombinePoint
        .ref GetCosValue,GetSinValue,BoundFill,MultipyValue
        .ref MaskTable,ThinTable,EdgePos,WindowPos
        .def DeltX,DeltY,Theta,MaskBitValue,CosValue,Dividen
        .def BlockLine,BlockCol,CoordX,CoordY,SinValue,Remain
        .def Divisor,Distance,SqrtValue,Sqrt_temp,Sqrt_root
        .def GraySize,GrayLevel,HorzBlock,SmoothTangle,Quoten
        .def AdjustMask1,AdjustMask2,AdjustMask3,Minus,VertBlock
        .def QuantizeTheta,ImageNormal,FilterRing,FreqValue               
        .def ThinImage,RegionMask,SmoothFreq,OrientImage,CalFrequency                
;---------------------------------------------------------------------------
; define variables used in enhance finger print image
;---------------------------------------------------------------------------
        .bss DeltX              ,2
        .bss DeltY              ,2
        .bss Dividen            ,2
        .bss FreqValue          ,2
        .bss Remain             ,2
        .bss Quoten             ,2

        .bss Divisor            ,1
        .bss Minus              ,1
        .bss SqrtValue          ,1
        .bss Sqrt_temp          ,1
        .bss Sqrt_root          ,1
        .bss Theta              ,1
        .bss GraySize           ,1
        .bss GrayMean           ,1
        .bss GrayVariance       ,1
        .bss MaxGrayVariance    ,1
        .bss MinGrayVariance    ,1
        .bss Threshold1         ,1
        .bss Threshold2         ,1
        .bss CoeffCount         ,1
        .bss ReDoing            ,1
        .bss WaveMax            ,1
        .bss WaveMin            ,1
        .bss WaveSum            ,1
        .bss WaveSize           ,1
        .bss WaveControl        ,1
        .bss Omiga              ,1
        .bss SubBand            ,1
        .bss SinValue           ,1
        .bss CosValue           ,1
        .bss GrayLevel          ,1
        .bss MaskBitValue       ,1
        .bss GapX               ,1
        .bss GapY               ,1
        .bss CoordX             ,1
        .bss CoordY             ,1
        .bss BlockLine          ,1
        .bss BlockCol           ,1
        .bss HorzBlock          ,1
        .bss VertBlock          ,1
        .bss OffsetLine         ,1
        .bss OffsetCol          ,1
        .bss Distance           ,1

        .text
****************************************************************************
* this function is used to enhance image by geometry,normalize the gray mean
* and gray variance value to desired value
* this can enhance the image visiblity,but do not change the image details
****************************************************************************
ImageNormal:
         ; calculate global image gray mean value
         SUB  A,A               ;graysum reset to zero
         STM  #IMAGEADDR,AR7
         RPT  #IMAGESIZE-1
         ADD  *AR7+,A           ;grasum=image pixels sum value 
         ST   #IMAGESIZE,Divisor
         RPT  #16-1
         SUBC Divisor,A         ;AL=dividen,AH=remainder
         STL  A,GrayMean

         ; calculate global image gray variance value
         SUB  B,B               ;grayvar reset to zero
         STM  #IMAGEADDR,AR7
         STM  #IMAGESIZE-1,BRC
         RPTB CAL_VAR_LOOP-1
         LD   *AR7+,16,A
         SUB  GrayMean,16,A     ;grayvar=image pixel variance sum
         ABS  A
         SQUR A,A
         ADD  A,B
CAL_VAR_LOOP
         ST    #IMAGESIZE,Divisor
         RPT   #15
         SUBC  Divisor,B         ;AL=dividen,AH=remainder
         STL   B,SqrtValue
         CALL  Sqroot            ;get sqrt value and save it
         MVDK  Sqrt_root,GrayVariance 

         ; normalize it using desired graymean and variance
         STM  #IMAGEADDR,AR7
         STM  #NORMALMEAN,T
         STM  #IMAGESIZE-1,BRC
         RPTB CAL_GRAY_LOOP-1
         LD   *AR7,16,B
         SUB  GrayMean,16,B
         ABS  B,A
         MPYA A
         RPT  #16-1
         SUBC GrayVariance,A
         AND  #00ffh,A
         BC   $1,BGEQ
         NEG  A
$1
         ADD  #NORMALVAR,A,B
         LD   #255,A
         MIN  B
         LD   #0,A
         MAX  B
         STL  B,*AR7+
CAL_GRAY_LOOP
         RET

****************************************************************************
* Function: RegionMask
* Description: thi subroutine is used to mask the block image,judge the area of
* block light value. so next time the block is enhanced or not enhanced
****************************************************************************
MeanArray  .usect  "region_bfr",BLOCKNUM
VarArray   .usect  "region_var",BLOCKNUM

         .text
RegionMask
         ; calculate block image gray mean value and save in mean array
         STM   #IMAGEWIDTH-BLOCKWIDTH,AR0
         STM   #MeanArray,AR1
         STM   #VarArray,AR2
         STM   #BLOCKSINY-1,AR3
         STM   #IMAGEADDR+STARTROW*IMAGEWIDTH+STARTCOL,AR7
CAL_BLOCK_VERTLOOP
         STM   #BLOCKSINX-1,AR4
CAL_BLOCK_HORZLOOP
         SUB   A,A              ;reset graysum to zero
         MVMM  AR7,AR6
         STM   #BLOCKHEIGHT-1,BRC
         RPTB  CAL_MEAN_BLOCKLINE
         RPT   #BLOCKWIDTH-1
         ADD   *AR6+,A          ;block image graysum
CAL_MEAN_BLOCKLINE
         MAR   *AR6+0           ;next block line
         STL   A,-8,*AR1        ;save into mean array for next time using

         ; calculate and save block gray variance value 
         SUB   B,B              ;reset gray sum
         MVMM  AR7,AR6
         STM   #BLOCKHEIGHT-1,AR5
CAL_VAR_BLOCKLINE
         STM   #BLOCKWIDTH-1,BRC
         RPTB  $2
         LD    *AR1,16,A           ;mean gray value
         SUB   *AR6+,16,A          ;graymean-grayvalue
         ABS   A
         SQUR  A,A
$2
         ADD   A,B
         MAR   *AR6+0
         BANZ  CAL_VAR_BLOCKLINE,*AR5-
         STL   B,-8,*AR2+
         MAR   *AR1+
         MAR   *+AR7(BLOCKWIDTH)
         BANZ  CAL_BLOCK_HORZLOOP,*AR4-
         MAR   *+AR7(IMAGEWIDTH*BLOCKHEIGHT-BLOCKSINX*BLOCKWIDTH)
         BANZ  CAL_BLOCK_VERTLOOP,*AR3-

         ; calculate block image maximize and minimum varinace value
         ST   #0,MaxGrayVariance
         ST   #65535,MinGrayVariance
         STM  #VarArray,AR4
         STM  #BLOCKNUM-1,BRC
         RPTB CAL_MAXMIN_VAR
         LD   *AR4+,A
         LD   MinGrayVariance,B
         MIN  B
         STL  B,MinGrayVariance
         LD   MaxGrayVariance,B
         MAX  B
CAL_MAXMIN_VAR 
         STL  B,MaxGrayVariance

         ; calculate two threshold for mask image block
         STM  #3,T
         LD   MaxGrayVariance,A
         MAC  MinGrayVariance,A
         STL  A,-2,Threshold1
         STM  #15,T
         LD   MaxGrayVariance,A
         MAC  MinGrayVariance,A
         STL  A,-4,Threshold2

         ; check image gray level,and catalogue into light array
         STM  #LightArray,AR3
         STM  #MeanArray,AR4
         STM  #VarArray,AR5
         STM  #BLOCKNUM-1,BRC
         RPTB CHECK_LEVEL_LOOP-1
         LD   Threshold2,B
         LD   GrayMean,A
         SUB  *AR4+,A
         BC   $3,AGT
         LD   Threshold1,B
$3
         SUB  A,A
         SUB  *AR5+,B
         BC   $4,BGT
         ADD  #3,A
$4
         STL  A,*AR3+
CHECK_LEVEL_LOOP
         RET  

****************************************************************************
* adjust the calculated image block light array,for smoothing image
****************************************************************************
Light2Array   .usect "adjust_bfr",BLOCKNUM
         .asg  ReDoing,ReAdjust

         .text
AdjustMask1:
         ST    #0,ReAdjust
         STM   #LightArray,AR4    ;copy the light array
         STM   #Light2Array,AR5
         RPT   #BLOCKNUM-1
         MVDD  *AR4+,*AR5+

         STM   #BLOCKSINY-3,AR2
         STM   #LightArray+BLOCKSINX+1,AR4
         STM   #Light2Array+BLOCKSINX+1,AR5
ADJUST_MASK1_LINE
         STM   #BLOCKSINX-3,AR3
ADJUST_MASK1_COL
         LD    *AR5,A         ;check lightarray value
         SUB   #2,A
         BC    ADJUST_MASK1_NEXT,AGEQ
         MVMM  AR5,AR1
         SUB   B,B
         STM   #2,AR6
         MAR   *+AR1(-BLOCKSINX-1)
ADJUST_MASK1_OFFSETY
         STM   #2,AR7
ADJUST_MASK1_OFFSETX
         LD    *AR1+,A
         SUB   #1,A
         BC    $1,ALT
         ADD   #1,B
$1
         BANZ  ADJUST_MASK1_OFFSETX,*AR7-
         MAR   *+AR1(BLOCKSINX-3)
         BANZ  ADJUST_MASK1_OFFSETY,*AR6-
         SUB   #5,B
         BC    ADJUST_MASK1_NEXT,BLEQ
         ST    #1,ReAdjust
         ST    #3,*AR4
ADJUST_MASK1_NEXT
         MAR   *AR4+
         MAR   *AR5+
         BANZ  ADJUST_MASK1_COL,*AR3-
         MAR   *+AR4(2)
         MAR   *+AR5(2)
         BANZ  ADJUST_MASK1_LINE,*AR2-
         CMPM  ReAdjust,#1
         BC    AdjustMask1,TC
         RET

****************************************************************************
* adjust the calculated image block light array,for smoothing image
****************************************************************************
         .text
AdjustMask2:
         SSBX  SXM
         STM   #LightArray,AR4    ;copy the light array
         STM   #Light2Array,AR5
         RPT   #BLOCKNUM-1
         MVDD  *AR4+,*AR5+

         STM   #LightArray ,AR4
         STM   #Light2Array,AR5
         ST    #0,VertBlock           
         STM   #BLOCKSINY-1,AR2        ;BlockLine  
ADJUST_MASK2_LINE
         ST    #0,HorzBlock
         STM   #BLOCKSINX-1,AR3        ;BlockCol
ADJUST_MASK2_COL
         LD    *AR5,A                  ;check lightarray value
         SUB   #1,A
         BC    ADJUST_MASK2_NEXT1,ALEQ
         SUB   B,B                     ;LightLevel=0
         MVMM  AR5,AR1
         LD    VertBlock,A
         SUB   #1,A
         STL   A,CoordY
         STM   #2,AR6                  ;offsetline
         MAR   *+AR1(-BLOCKSINX-1)
ADJUST_MASK2_LINE_LOOP
         LD    HorzBlock,A
         SUB   #1,A
         STL   A,CoordX
         STM   #2,AR7                  ;offsetcol
ADJUST_MASK2_COL_LOOP
         BC    ADJUST_MASK2_INC,ALT
         SUB   #BLOCKSINX,A
         BC    ADJUST_MASK2_INC,AGEQ
         LD    CoordY,A
         BC    ADJUST_MASK2_INC,ALT
         SUB   #BLOCKSINX,A
         BC    ADJUST_MASK2_INC,AGEQ
         LD    *AR1,A
         SUB   #2,A
         BC    ADJUST_MASK2_NEXT2,AGEQ
ADJUST_MASK2_INC:
         ADD   #1,B
ADJUST_MASK2_NEXT2
         LD    CoordX,A
         ADD   #1,A
         STL   A,CoordX
         MAR   *AR1+
         BANZ  ADJUST_MASK2_COL_LOOP,*AR7-
         LD    CoordY,A
         ADD   #1,A
         STL   A,CoordY
         MAR   *+AR1(BLOCKSINX-3)
         BANZ  ADJUST_MASK2_LINE_LOOP,*AR6-
         SUB   #5,B
         BC    ADJUST_MASK2_NEXT1,BLEQ
         MVKD  #1,*AR4
ADJUST_MASK2_NEXT1
         MAR   *AR4+
         MAR   *AR5+
         LD    HorzBlock,A
         ADD   #1,A
         STL   A,HorzBlock
         BANZ  ADJUST_MASK2_COL,*AR3-
         LD    VertBlock,A
         ADD   #1,A
         STL   A,VertBlock
         BANZ  ADJUST_MASK2_LINE,*AR2-
         RSBX  SXM
         RET

****************************************************************************
* image masking adjust,using masking table here
****************************************************************************
        .text
AdjustMask3:
        SSBX  SXM
        STM   #IMAGEADDR-IMAGEOFF+STARTROW*IMAGEWIDTH+STARTCOL,AR5
        STM   #LightArray,AR6
        STM   #BLOCKSINY-1,BRC
        RPTB  ADJUST_MASK3_LOOP-1
        STM   #BLOCKSINX-1,AR7
ADJUST_MASK3_BLOCK
        LD    *AR6,A                 ;get lightlevel
        SUB   #2,A
        BC    ADJUST_MASK3_NEXT,ALT
        PSHM  AR7
        MVMM  AR5,AR1
        ST    #0,GrayLevel
        STM   #BLOCKHEIGHT-1,AR4
ADJUST_MASK3_LINE
        STM   #BLOCKWIDTH-1,AR3
ADJUST_MASK3_COL
        LD    *AR1,A
        BC    ADJUST_MASK3_NEXTCOL,AEQ
        SUB   B,B
        ST    #0080h,MaskBitValue
        STM   #EdgePos,AR7
        STM   #8-1,AR2
MASK_LOOP
        LDM   AR1,A
        ADD   *AR7+,A
        STLM  A,AR0
        NOP
        NOP
        LD    *AR0,A
        BC    MASK_LOOP_NEXT,AEQ
        XOR   MaskBitValue,B
MASK_LOOP_NEXT
        LD    MaskBitValue,-1,A
        STL   A,MaskBitValue
        BANZ  MASK_LOOP,*AR2-
        ADD   #MaskTable,B
        STLM  B,AR0
        NOP
        NOP
        LD    *AR0,A
        BC    ADJUST_MASK3_NEXTCOL,AEQ
        LD    GrayLevel,A
        ADD   #1,A
        STL   A,GrayLevel
ADJUST_MASK3_NEXTCOL
        MAR   *AR1+
        BANZ  ADJUST_MASK3_COL,*AR3-
        MAR   *+AR1(IMAGEWIDTH-BLOCKWIDTH)
        BANZ  ADJUST_MASK3_LINE,*AR4-
        POPM  AR7
        LD    GrayLevel,B
        SUB   #4,B
        BC    ADJUST_MASK3_NEXT,BLEQ
        ST    #1,*AR6
ADJUST_MASK3_NEXT
        MAR   *AR6+
        MAR   *+AR5(BLOCKWIDTH)
        BANZ  ADJUST_MASK3_BLOCK,*AR7-
        MAR   *+AR5(IMAGEWIDTH*BLOCKHEIGHT-BLOCKSINX*BLOCKWIDTH)
ADJUST_MASK3_LOOP
        RSBX  SXM
        RET

****************************************************************************
* calculate the finger print orientation image
* using sobel method to cal the tan angle
****************************************************************************
        .text
OrientImage:
        STM   #IMAGEWIDTH,AR0
        STM   #IMAGEADDR+STARTROW*IMAGEWIDTH+STARTCOL,AR3
        STM   #LightArray,AR5
        STM   #ThetaArray,AR6
        STM   #BLOCKSINY-1,BRC
        RPTB  ORIENT_LOOP_LINE-1
        STM   #BLOCKSINX-1,AR7
ORIENT_LOOP_COL
        ST    #90,Theta
        CMPM  *AR5+,#0             ;lightarray[]=0?
        BC    ORIENT_LOOP_NEXT,TC
        SUB   A,A
        STM   #DeltX,AR1
        DST   A,*AR1
        STM   #DeltY,AR1
        DST   A,*AR1
        MVMM  AR3,AR1
        STM   #BLOCKHEIGHT-3,AR4
		NOP
        MAR   *+AR1(IMAGEWIDTH+1)
CAL_GAP_LINELOOP
        STM   #BLOCKWIDTH-3,AR2
CAL_GAP_COLLOOP
        MAR   *AR1-         ;                         p5==>p4
        LD    *AR1-0,1,A    ;A=2*p4                   p4==>p1
        ADD   *AR1,A        ;A=2*p4+p1                p1==>p1
        LD    *AR1+,B       ;B=p1                     p1==>p2
        ADD   *AR1+,1,B     ;B=p1+2*p2                p2==>p3
        SUB   *AR1,A        ;A=2*p4+p1-p3             p3==>p3
        ADD   *AR1+0,B      ;B=p1+2*p2+p3             p3==>p6
        SUB   *AR1+0,1,A    ;A=2*p4+p1-p3-2*p6        p6==>p9
        SUB   *AR1,A        ;A=2*p4+p1-p3-2*p6-p9     p9==>p9
        SUB   *AR1-,B       ;B=p1+2*p2+p3-p9          p9==>p8
        SUB   *AR1-,1,B     ;B=p1+2*p2+p3-p9-2*p8     p8==>p7
        ADD   *AR1,A        ;A=2*p4+p1-p3-2*p6-p9+p7  p7==>p7
        SUB   *AR1-0,B      ;B=p1+2*p2+p3-p9-2*p8-p7  p7==>p4
        MAR   *+AR1(2)      ;                         p4==>p5
        PSHM  AR1
        STL   A,GapX         
        STL   B,GapY
        LD    GapX,T        ;T=GapX
        MPY   GapY,A        ;A=GapX*GapY
        STM   #DeltY,AR1   
        DLD   *AR1,B
        ADD   A,1,B         ;DistanceY+=2*GapX*GapY
        DST   B,*AR1
        MPY   GapX,B        ;B=GapX*GapX
        LD    GapY,T        ;T=GapY
        MAS   GapY,B        ;B=GapX*GapX-GapY*GapY
        STM   #DeltX,AR1
        DLD   *AR1,A
        ADD   A,B           ;DistanceX+=GapX*GapX-GapY*GapY
        DST   B,*AR1
        POPM  AR1
        BANZ  CAL_GAP_COLLOOP,*AR2-
        MAR   *+AR1(IMAGEWIDTH-BLOCKWIDTH+2)
        BANZ  CAL_GAP_LINELOOP,*AR4-
        CALL  CalAngle      ;Theta=atan(DeltY/DeltX)
ORIENT_LOOP_NEXT
        LD    Theta,A
        STL   A,*AR6+
        MAR   *+AR3(BLOCKWIDTH)
        BANZ  ORIENT_LOOP_COL,*AR7-
        MAR   *+AR3(IMAGEWIDTH*BLOCKHEIGHT-BLOCKSINX*BLOCKWIDTH)
ORIENT_LOOP_LINE
        RET

****************************************************************************
* smooth the calcuated block image angle,in neighbour area 5*5
****************************************************************************
AlphaArray    .usect  "smooth_bfr",BLOCKNUM

        .text
SmoothTangle:
        SSBX SXM
        STM  #AlphaArray,AR5
        STM  #ThetaArray,AR4
        RPT  #BLOCKNUM-1
        MVDD *AR4+,*AR5+
        NOP
        NOP
        STM  #LightArray,AR4
        STM  #AlphaArray,AR5
        STM  #ThetaArray,AR6
        ST   #0,VertBlock
        STM  #BLOCKSINY-1,BRC
        RPTB SMOOTH_BLOCK_LINE-1
        STM  #BLOCKSINX-1,AR2
        ST   #0,HorzBlock
SMOOTH_BLOCK_COL
        LD   *AR4,A
        BC   NEXT_SMOOTH_LOOP,AEQ
        PSHM AR6
        STM  #DeltX,AR6
        SUB  A,A
        DST  A,*AR6
        STM  #DeltY,AR6
        DST  A,*AR6
        MVMM AR4,AR0
        LD   VertBlock,A
        SUB  #2,A
        MAR  *+AR0(-2*BLOCKSINX-2)
        MVMM AR5,AR3
        STL  A,CoordY
        STM  #4,AR1
        MAR  *+AR3(-2*BLOCKSINX-2)
SMOOTH_OFFSET_LINE
        LD   HorzBlock,A
        SUB  #2,A
        STL  A,CoordX
        STM  #4,AR7
SMOOTH_OFFSET_COL
        BC   NEXT_SMOOTH_OFFSET,ALT
        SUB  #BLOCKSINX,A
        BC   NEXT_SMOOTH_OFFSET,AGEQ
        LD   CoordY,A
        BC   NEXT_SMOOTH_OFFSET,ALT
        SUB  #BLOCKSINY,A
        BC   NEXT_SMOOTH_OFFSET,AGEQ
        CMPM *AR0,#0
        BC   NEXT_SMOOTH_OFFSET,TC
        CMPM *AR0,#2
        BC   NEXT_SMOOTH_OFFSET,TC
        LD   CoordX,A
        SUB  HorzBlock,A
        ABS  A
        LD   CoordY,B
        SUB  VertBlock,B
        ABS  B
        MAX  B
        LD   #3,A
        SUB  B,A
        STL  A,Distance
        SQUR Distance,A
        STL  A,Distance
        MPY  Distance,B
        STL  B,Distance
        
		LD   *AR3,1,B
        STL  B,Theta
        CALL GetCosValue
        MPYA Distance
        CMPM Minus,#1
        BC   $12,TC
        CMPM Minus,#4
        BC   $12,TC
        NEG  B
$12
        STM  #DeltX,AR6
        DLD  *AR6,A
        ADD  A,B
        DST  B,*AR6
        CALL GetSinValue
        MPYA Distance
        CMPM Minus,#1
        BC   $22,TC
        CMPM Minus,#2
        BC   $22,TC
        NEG  B
$22
        STM  #DeltY,AR6
        DLD  *AR6,A
        ADD  A,B
        DST  B,*AR6
NEXT_SMOOTH_OFFSET
        MAR  *AR0+
        MAR  *AR3+
        LD   CoordX,A
        ADD  #1,A
        STL  A,CoordX
        BANZ SMOOTH_OFFSET_COL,*AR7-
        MAR  *+AR0(BLOCKSINX-5)
        MAR  *+AR3(BLOCKSINX-5)
        LD   CoordY,A
        ADD  #1,A
        STL  A,CoordY
        BANZ SMOOTH_OFFSET_LINE,*AR1-
        CALL ReCalAngle
        POPM AR6
        LD   Theta,A
        STL  A,*AR6
NEXT_SMOOTH_LOOP
        LD   HorzBlock,A
        ADD  #1,A
        STL  A,HorzBlock
        MAR  *AR4+
        MAR  *AR5+
        MAR  *AR6+
        BANZ SMOOTH_BLOCK_COL,*AR2-
        LD   VertBlock,A
        ADD  #1,A
        STL  A,VertBlock
SMOOTH_BLOCK_LINE
        RSBX SXM   
        RET

****************************************************************************
* Quantize the calculate angle into six catalogue 0--15
****************************************************************************
        .text
QuantizeTheta
        STM  #ThetaArray,AR6
        ST   #45,Sqrt_temp
        STM  #BLOCKNUM-1,BRC
        RPTB QUANTIZE_LOOP
        LD   *AR6,4,A       ;Theta*16
        RPT  #15
        SUBC Sqrt_temp,A

        AND  #0ffffh,A
        ADD  #2,A
        SFTA A,-2,A         ;Theta=(Theta*16/45+2)/4
        SUB  #16,A,B
        BC   QUANTIZE_LOOP,BLT
        AND  #0h,A
QUANTIZE_LOOP
        STL  A,*AR6+
        RET

****************************************************************************
* calcuate the finger print frequency using garbo filter
* assume the image is weave,and has direction oriented
****************************************************************************
WaveData        .usect "freq_var",32
WaveForm        .usect "freq_var",32
         .text
CalFrequency:
         SSBX SXM 
         STM  #FreqArray,AR6
         RPT  #BLOCKNUM-1     ;Fill FreqArray to -1
         ST   #-1,*AR6+

         STM  #IMAGEADDR+(STARTROW+BLOCKHEIGHT+BLOCKHEIGHT2)*IMAGEWIDTH+STARTCOL+BLOCKWIDTH+BLOCKWIDTH2,AR2
         STM  #ThetaArray+BLOCKSINX+1,AR4
         STM  #LightArray+BLOCKSINX+1,AR5
         STM  #FreqArray+BLOCKSINX+1,AR6
         STM  #BLOCKSINY-3,BRC
         RPTB CAL_FREQ_LINE-1
         STM  #BLOCKSINX-3,AR3
CAL_FREQ_COL
         MVDK *AR4+,Theta       ;Theta=ThetaArray
         ST   #-1,Omiga
         LD   *AR5+,A          ;LightArray
         BC   SAVE_NEXT_FREQ,AEQ
         PSHM AR3
         PSHM AR4
         PSHM AR6
         MVMM AR2,AR6
         STM  #WaveData,AR3
         STM  #BANDHEIGHT-1,AR1
         LD   Theta,9,A
         ADD  #WindowPos,A
         STLM A,AR4             ;AR4=WindosPos[Theta][0][0]
BAND_HEIGHT_LOOP
         SUB  B,B
         STM  #BANDWIDTH-1,AR7
BAND_WIDTH_LOOP
         LDM  AR6,A
         ADD  *AR4+,A
         STLM A,AR0
         NOP
         NOP
         ADD  *AR0,B
         BANZ BAND_WIDTH_LOOP,*AR7-
         SFTA B,-4,B
         STL  B,*AR3+
         BANZ BAND_HEIGHT_LOOP,*AR1-

         STM  #FILTERFREQ-1,AR1
FILTERFORM_LOOP
         STM  #WaveData,AR3
         STM  #WaveForm,AR4
         LD   *AR3+,A
         ADD  *AR3,A
         STL  A,-1,*AR4+
         STM  #BANDHEIGHT-3,AR7
FILTERWAVE_LOOP
         MAR  *AR3-
         LD   *AR3+,A
         ADD  *AR3+,1,A
         ADD  *AR3,A
         STL  A,-2,*AR4+
         BANZ FILTERWAVE_LOOP,*AR7-
         LD   *AR3-,A
         ADD  *AR3,A
         STL  A,-1,*AR4
         STM  #WaveData,AR3
         STM  #WaveForm,AR4
         RPT  #BANDHEIGHT-1
         MVDD *AR4+,*AR3+
         NOP
         NOP
         BANZ FILTERFORM_LOOP,*AR1-

         ; find the wave band width and wave form
         STM  #WaveData,AR3
         STM  #WaveForm,AR4
         SUB  B,B
         ST   #0,WaveControl
         STM  #BANDHEIGHT-2,AR1
FIND_WAVE_LOOP
         CMPM WaveControl,#0
         BC   FIND_CONTROL1,NTC
FIND_CONTROL0
         LD   *AR3+,A
         SUB  *AR3-,A
         BC   FIND_ALEQ0,ALEQ
         ST   #1,WaveControl
         B    FIND_WAVE_NEXT
FIND_ALEQ0
         BC   FIND_WAVE_NEXT,AEQ
         ST   #-1,WaveControl
         B    FIND_WAVE_NEXT
FIND_CONTROL1
         CMPM WaveControl,1
         BC   FIND_CONTROLN1,NTC
         LD   *AR3+,A
         SUB  *AR3-,A
         BC   FIND_WAVE_NEXT,AGEQ
         ST   #-1,WaveControl
         ADD  #1,B
         LDM  AR3,A
         SUB  #WaveData,A
         STL  A,*AR4+
         B    FIND_WAVE_NEXT
FIND_CONTROLN1
         LD   *AR3+,A
         SUB  *AR3-,A
         BC   FIND_WAVE_NEXT,ALEQ
         ST   #1,WaveControl
         ADD  #1,B
         LDM  AR3,A
         SUB  #WaveData,A
         STL  A,*AR4+
FIND_WAVE_NEXT
         MAR  *AR3+
         BANZ FIND_WAVE_LOOP,*AR1-

         ; find the maximize and minium length,then calculate frequency
         ST   #255,WaveMin
         ST   #0,WaveMax
         STL  B,WaveSize
         SUB  #2,B
         BC   CAL_OMIGA_VALUE,BLT
         STM  #WaveForm,AR4
         STLM B,AR7
FIND_MAX_MIN
         MAR  *AR4+
         LD   *AR4-,A
         SUB  *AR4+,A
         LD   WaveMax,B
         MAX  B
         STL  B,WaveMax
         LD   WaveMin,B
         MIN  B
         STL  B,WaveMin
         BANZ FIND_MAX_MIN,*AR7-
CAL_OMIGA_VALUE
         LD   WaveSize,B
         ST   #-1,Omiga
         SUB  #3,B,A
         BC   RESTORE_SAVE_NEXT_FREQ,ALT
         LD   WaveMax,A
         SUB  WaveMin,A
         SUB  #4,A
         BC   RESTORE_SAVE_NEXT_FREQ,AGT
         SUB  #1,B
         STLM B,AR0
         STL  B,WaveSize
         STM  #WaveForm,AR4
         MAR  *AR4+0
         LD   *AR4-0,1,A
         SUB  *AR4,1,A
         RPT  #15
         SUBC WaveSize,A
         STL  A,Omiga
RESTORE_SAVE_NEXT_FREQ
         POPM AR6  
         POPM AR4
         POPM AR3
SAVE_NEXT_FREQ
         ; save the frequency value into data array
         LD   Omiga,A
         SUB  #MAXFREQUENCY,A,B
         BC   SAVE_FREQ_NOCHANGE,BGT
         SUB  #MINFREQUENCY,A,B
         BC   SAVE_FREQ_NOCHANGE,BLT
         ABS  A            ;|Omiga|
         STL  A,Omiga
         LD   #32767,A
         ADD  #1,A
         RPT  #15
         SUBC Omiga,A       ;32768/abs(Omiga)
         B    SAVE_THE_FREQ
SAVE_FREQ_NOCHANGE
         LD   #-1,A
SAVE_THE_FREQ
         STL  A,*AR6+
         MAR  *+AR2(BLOCKWIDTH)
         BANZ  CAL_FREQ_COL,*AR3-
         MAR  *+AR2(BLOCKHEIGHT*IMAGEWIDTH-BLOCKWIDTH*(BLOCKSINX-2))
         MAR  *+AR4(2)
         MAR  *+AR5(2)
         MAR  *+AR6(2)
CAL_FREQ_LINE
         RSBX SXM 
         RET

****************************************************************************
* smoothe the calculated frequency value
****************************************************************************
FreqReserve .usect "freq_bfr",BLOCKNUM
         
        .asg ReDoing,ReSmooth
        .text
SmoothFreq:
        SSBX SXM
        ST   #0,ReSmooth
        STM  FreqArray,AR4
        STM  FreqReserve,AR5
        RPT  #BLOCKNUM-1
        MVDD *AR4+,*AR5+

        ST   #0,VertBlock
        STM  FreqArray,AR4
        STM  #FreqReserve-2*BLOCKSINX-2,AR5
        STM  #BLOCKSINY-1,AR6
SMOOTH_FREQ_LINE
        ST   #0,HorzBlock
        STM  #BLOCKSINX-1,AR7
SMOOTH_FREQ_COL
        LD   VertBlock,A
        SUB  #2,A
        STL  A,CoordY
        STM  #4,AR2
        SUB  B,B
        ST   #0,GraySize
        MVMM AR5,AR1
SMOOTH_FREQ_OFFLINE
        BC   NEXT_SMOOTH_FREQ_OFFLINE,ALT
        SUB  #BLOCKSINY,A
        BC   NEXT_SMOOTH_FREQ_OFFLINE,AGEQ
        MVMM AR1,AR0
        LD   HorzBlock,A
        SUB  #2,A
        STL  A,CoordX
        STM  #4,AR3
SMOOTH_FREQ_OFFCOL
        BC   NEXT_SMOOTH_FREQ_OFFCOL,ALT
        SUB  #BLOCKSINX,A
        BC   NEXT_SMOOTH_FREQ_OFFCOL,AGEQ
        LD   *AR0,A
        BC   NEXT_SMOOTH_FREQ_OFFCOL,ALEQ
        ADD  A,B
        LD   GraySize,A
        ADD  #1,A
        STL  A,GraySize
NEXT_SMOOTH_FREQ_OFFCOL
        MAR  *AR0+
        LD   CoordX,A
        ADD  #1,A
        STL  A,CoordX
        BANZ SMOOTH_FREQ_OFFCOL,*AR3-
NEXT_SMOOTH_FREQ_OFFLINE
        MAR  *+AR1(BLOCKSINX)
        LD   CoordY,A
        ADD  #1,A
        STL  A,CoordY
        BANZ SMOOTH_FREQ_OFFLINE,*AR2-
        LD   GraySize,A
        BC   NOT_FREQ_CAL,AEQ
        RPT  #15
        SUBC GraySize,B
        STL  B,*AR4+
        B    NEXT_SMOOTH_FREQ_COL   
NOT_FREQ_CAL
        ST   #-1,*AR4+
        ST   #1,ReSmooth
NEXT_SMOOTH_FREQ_COL
        MAR  *AR5+
        LD   HorzBlock,A
        ADD  #1,A
        STL  A,HorzBlock
        BANZ SMOOTH_FREQ_COL,*AR7-
        LD   VertBlock,A
        ADD  #1,A
        STL  A,VertBlock
        BANZ SMOOTH_FREQ_LINE,*AR6-
        CMPM ReSmooth,#1
        BC   SmoothFreq,TC
        RSBX SXM
        RET

****************************************************************************
* Filter finger image into segmeant image
****************************************************************************
BlockData   .usect "filter_bfr",BLOCKSIZE
CosData     .usect "filter_bfr",BLOCKHEIGHT
SinData     .usect "filter_bfr",BLOCKHEIGHT
Coeff       .usect "filter_bfr",81

        .text
FilterRing:
        SSBX SXM
        SUB  B,B
        STM  #CosData,AR4
        STM  #SinData,AR5
        STM  #BLOCKHEIGHT-1,BRC
        RPTB SAVE_COSSIN_DATA-1
        STL  B,BlockLine
        ADD  #2,B,A
        STL  A,-2,Theta
        CALL GetCosValue
        CMPM Minus,#1
        BC   $11,TC
        CMPM Minus,#4
        BC   $11,TC
        NEG  A
$11
        STH  A,*AR4+
        CALL GetSinValue
        CMPM Minus,#1
        BC   $21,TC
        CMPM Minus,#2
        BC   $21,TC
        NEG  A
$21
        STH  A,*AR5+
        LD   BlockLine,B
        ADD  #45,B
SAVE_COSSIN_DATA

        STM  #FreqArray,AR3
        STM  #ThetaArray,AR4
        STM  #LightArray,AR5
        STM  #IMAGEADDR+STARTROW*IMAGEWIDTH+STARTCOL,AR6
        STM  #BLOCKSINY-1,BRC
        RPTB FILTER_LOOP_LINE-1
        STM  #BLOCKSINX-1,AR2
FILTER_LOOP_COL
        CMPM *AR5+,#0
        BC   BLOCK_RESTORE,NTC

        ; none restorable image block area
        MVMM AR6,AR1
        STM  #BLOCKHEIGHT-1,AR7
        MAR  *AR4+
        MAR  *AR3+
		MAR  *+AR1(-IMAGEOFF)
FILLBLOCK_LOOP
        RPT  #BLOCKWIDTH-1
        ST   #BLACK,*AR1+
        MAR  *+AR1(IMAGEWIDTH-BLOCKWIDTH)
        BANZ FILLBLOCK_LOOP,*AR7-
        B    FILTER_NEXT_COL

        ; restorable image block area
BLOCK_RESTORE
        PSHM AR2
        LD   *AR4+,A
        STL  A,Theta
        ADD  #CosData,A,B
        STLM B,AR1
        ADD  #SinData,A,B
        STLM B,AR2
        LD   *AR3+,A
        ABS  A
        STL  A,FreqValue
        PSHM AR3
        PSHM AR4
        PSHM AR5
        STM  #Coeff,AR0
        STM  #DeltY  ,AR5
        STM  #Coeff  ,AR7
        ST   #-4,OffsetLine
CAL_COEFF_LINE
        ST   #-4,OffsetCol
CAL_COEFF_COL
        LD   OffsetCol,A
        LD   *AR2,B
        CALL MultipyValue
        DST  B,*AR5
        LD   OffsetLine,A
        LD   *AR1,B
        CALL MultipyValue
        DLD  *AR5,A
        SUB  B,A
        ABS  A
        SFTA A,-3,A
        STLM A,T
        MPY  FreqValue,A
        SFTA A,5,A
        STM  #360,T
        MPYA A
        SFTA A,-16,A
        STL  A,Theta
        CALL GetCosValue
        CMPM Minus,#1
        BC   $13,TC
        CMPM Minus,#4
        BC   $13,TC
        NEG  A
$13
        STH  A,*AR7+
NEXT_FILTER_OFFSETCOL                 
        LD   OffsetCol,A
        ADD  #1,A
        STL  A,OffsetCol
        CMPM OffsetCol,#5
        BC   CAL_COEFF_COL,NTC
NEXT_FILTER_OFFSETLINE                 
        LD   OffsetLine,A
        ADD  #1,A
        STL  A,OffsetLine
        CMPM OffsetLine,#5
        BC   CAL_COEFF_LINE,NTC

        ; calculate block image threshold
        PSHM AR6
        SUB  B,B
        STM  #BlockData,AR7
        ST   #0,BlockLine
THRESHOLD_SUM_LINE
        ST   #0,BlockCol
THRESHOLD_SUM_COL
        SUB  A,A             ;GraySum=0
        STM  #3,AR4
        MVMM AR6,AR1
        STM  #Coeff,AR3
        STM  #4*IMAGEWIDTH+4,AR0
SUM_GRAY_LINE
        STM  #8,AR5
SUM_GRAY_COL
        MAR  *AR1-0
        LD   *AR1+0,T
        MAC  *AR3,A
        MAR  *AR1+0
        LD   *AR1-0,T
        MAC  *AR3+,A
        MAR  *AR0-
        BANZ SUM_GRAY_COL,*AR5-
        MAR  *+AR0(-IMAGEWIDTH+9)
        BANZ SUM_GRAY_LINE,*AR4-
        MVMM AR6,AR1
        STM  #4,AR0
        STM  #3,AR4
SUM_GRAY_CON
        MAR  *AR1-0
        LD   *AR1+0,T
        MAC  *AR3,A
        MAR  *AR1+0
        LD   *AR1-0,T
        MAC  *AR3+,A
        MAR  *AR0-
        BANZ SUM_GRAY_CON,*AR4-
        LD   *AR1,T
        MAC  *AR3,A
        SFTA A,-15,A
        ADD  #8000h,A
        AND  #0ffffh,A
        STL  A,*AR7+
        ADD  A,B            
        LD   BlockCol,A
        ADD  #1,A
        STL  A,BlockCol
        MAR  *AR6+
        SUB  #BLOCKWIDTH,A
        BC   THRESHOLD_SUM_COL,ALT
        LD   BlockLine,A
        ADD  #1,A
        STL  A,BlockLine
        MAR  *+AR6(IMAGEWIDTH-BLOCKWIDTH)
        SUB  #BLOCKHEIGHT,A
        BC   THRESHOLD_SUM_LINE,ALT
        POPM AR6
        SFTL B,-8,B
        MVMM AR6,AR1
        STM  #BlockData,AR5
        STM  #BLOCKHEIGHT-1,AR7
        MAR  *+AR1(-IMAGEOFF)
THRESHOLD_LINE_LOOP
        STM  #BLOCKWIDTH-1,AR3
THRESHOLD_COL_LOOP
        ST   #BLACK,*AR1
        LD   *AR5+,A
        AND  #0ffffh,A
        SUB  B,A
        BC   FILTER_BLACK,AGT
        ST   #WHITE,*AR1
FILTER_BLACK
        MAR  *AR1+
        BANZ THRESHOLD_COL_LOOP,*AR3-
        MAR  *+AR1(IMAGEWIDTH-BLOCKWIDTH)
        BANZ THRESHOLD_LINE_LOOP,*AR7-
        POPM AR5
        POPM AR4
        POPM AR3
        POPM AR2
FILTER_NEXT_COL
        MAR  *+AR6(BLOCKWIDTH)
        BANZ FILTER_LOOP_COL,*AR2-
        MAR  *+AR6(BLOCKHEIGHT*IMAGEWIDTH-BLOCKWIDTH*BLOCKSINX)
FILTER_LOOP_LINE
        RSBX SXM
        CALL BoundFill
        RET

****************************************************************************
* Thinning the segmeant image into one pixels
****************************************************************************
        .text
ThinImage:
        STM  #IMAGEWIDTH,AR0
        ST   #0,ReSmooth       ;set rethining flag

        ;thining up line point
        STM  #IMAGEADDR-IMAGEOFF,AR6
        STM  #IMAGESIZE-1,BRC
        RPTB COPYIMAGE_UP-1
        LD   *AR6,4,A
        ANDM #00fh,*AR6
        OR   *AR6,A
        AND  #0ffh,A
        STL  A,*AR6+
COPYIMAGE_UP
        STM  #IMAGEADDR-IMAGEOFF+IMAGEWIDTH+1,AR6
        STM  #IMAGEHEIGHT-3,AR4
THIN_UP_LINE
        STM  #IMAGEWIDTH-3,AR3
THIN_UP_COL
        LD   *AR6,-4,A           ;current point
        SUB  #WHITE,A
        BC   NEXT_THIN_UP,ANEQ
        MAR  *AR6-0              ;top point
        LD   *AR6+0,-4,A
        SUB  #BLACK,A
        BC   NEXT_THIN_UP,ANEQ
        CALL CombinePoint
        ADD  #ThinTable,A
        STLM A,AR5
        NOP
        NOP
        LD   *AR5,B
        BC   NEXT_THIN_UP,BNEQ
        ANDM #0f0h,*AR6
        ST   #1,ReSmooth
NEXT_THIN_UP
        MAR  *AR6+
        BANZ THIN_UP_COL,*AR3-
        MAR  *+AR6(2)
        BANZ THIN_UP_LINE,*AR4-

        ;thining bottom line point	
        STM  #IMAGEADDR-IMAGEOFF,AR6
        STM  #IMAGESIZE-1,BRC
        RPTB COPYIMAGE_BOTTOM-1
        LD   *AR6,4,A
        ANDM #00fh,*AR6
        OR   *AR6,A
        AND  #0ffh,A
        STL  A,*AR6+
COPYIMAGE_BOTTOM
        STM  #IMAGEADDR-IMAGEOFF+IMAGEWIDTH+1,AR6
        STM  #IMAGEHEIGHT-3,AR4
THIN_BOTTOM_LINE
        STM  #IMAGEWIDTH-3,AR3
THIN_BOTTOM_COL
        LD   *AR6,-4,A           ;current point
        SUB  #WHITE,A
        BC   NEXT_THIN_BOTTOM,ANEQ
        MAR  *AR6+0              ;bottom point
        LD   *AR6-0,-4,A
        SUB  #BLACK,A
        BC   NEXT_THIN_BOTTOM,ANEQ
        CALL CombinePoint
        ADD  #ThinTable,A
        STLM A,AR5
        NOP
        NOP
        LD   *AR5,B
        BC   NEXT_THIN_BOTTOM,BNEQ
        ANDM #0f0h,*AR6
        ST   #1,ReSmooth
NEXT_THIN_BOTTOM
        MAR  *AR6+
        BANZ THIN_BOTTOM_COL,*AR3-
        MAR  *+AR6(2)
        BANZ THIN_BOTTOM_LINE,*AR4-

        ;thining left line point
        STM  #IMAGEADDR-IMAGEOFF,AR6
        STM  #IMAGESIZE-1,BRC
        RPTB COPYIMAGE_LEFT-1
        LD   *AR6,4,A
        ANDM #00fh,*AR6
        OR   *AR6,A
        AND  #0ffh,A
        STL  A,*AR6+
COPYIMAGE_LEFT
        STM  #IMAGEADDR-IMAGEOFF+IMAGEWIDTH+1,AR6
        STM  #IMAGEHEIGHT-3,AR4
THIN_LEFT_LINE
        STM  #IMAGEWIDTH-3,AR3
THIN_LEFT_COL
        LD   *AR6,-4,A           ;current point
        SUB  #WHITE,A
        BC   NEXT_THIN_LEFT,ANEQ
        MAR  *AR6-               ;left point
        LD   *AR6+,-4,A
        SUB  #BLACK,A
        BC   NEXT_THIN_LEFT,ANEQ
        CALL CombinePoint
        ADD  #ThinTable,A
        STLM A,AR5
        NOP
        NOP
        LD   *AR5,B
        BC   NEXT_THIN_LEFT,BNEQ
        ANDM #0f0h,*AR6
        ST   #1,ReSmooth
NEXT_THIN_LEFT
        MAR  *AR6+
        BANZ THIN_LEFT_COL,*AR3-
        MAR  *+AR6(2)
        BANZ THIN_LEFT_LINE,*AR4-

        ;thining right line point
        STM  #IMAGEADDR-IMAGEOFF,AR6
        STM  #IMAGESIZE-1,BRC
        RPTB COPYIMAGE_RIGHT-1
        LD   *AR6,4,A
        ANDM #00fh,*AR6
        OR   *AR6,A
        AND  #0ffh,A
        STL  A,*AR6+
COPYIMAGE_RIGHT
        STM  #IMAGEADDR-IMAGEOFF+IMAGEWIDTH+1,AR6
        STM  #IMAGEHEIGHT-3,AR4
THIN_RIGHT_LINE
        STM  #IMAGEWIDTH-3,AR3
THIN_RIGHT_COL
        LD   *AR6,-4,A           ;current point
        SUB  #WHITE,A
        BC   NEXT_THIN_RIGHT,ANEQ
        MAR  *AR6+               ;right point
        LD   *AR6-,-4,A
        SUB  #BLACK,A
        BC   NEXT_THIN_RIGHT,ANEQ
        CALL CombinePoint
        ADD  #ThinTable,A
        STLM A,AR5
        NOP
        NOP
        LD   *AR5,B
        BC   NEXT_THIN_RIGHT,BNEQ
        ANDM #0f0h,*AR6
        ST   #1,ReSmooth
NEXT_THIN_RIGHT
        MAR  *AR6+
        BANZ THIN_RIGHT_COL,*AR3-
        MAR  *+AR6(2)
        BANZ THIN_RIGHT_LINE,*AR4-

        CMPM ReSmooth,#1
        BC   ThinImage,TC
        RET
;----------------------------------------------------------------------------

